﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.ServiceModel;
using App.Business.Entities.Party;
using App.Business.Party;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RrslLite.Configuration;
using RrslLite.Dsl;
using RrslLite.Net;
using RrslLite.Net.Attributes;
using RrslLite.Net.BatchImpl;
using RrslLite.Net.Messages;
using RrslLite.Net.Proxies;

namespace App.Test.Silverlight
{
    [TestClass]
    public class BatchFactory_Async_TEST
    {
        [TestInitialize]
        public void Init()
        {
            RrslLiteConfiguration.Instance.WithDefaultBatchBuilderConfiguration();

            RrslLiteConfiguration.Instance.BatchBuilderConfiguration
                .WithCreateClassProxyWithTargetRecursiveToReceiveMessages()
                .WithINotifyPropertyChangedInterceptorToReceiveMessages()
                ;
            KnownTypeProvider.RegisterModelDomainNamespace("App.Business.Entities");
        }

        [TestMethod]
        public void BatchFactoryTEST_FluentConfiguration()
        {
            IBatchBuilder factory = new AsyncBatchBuilder();

            factory
                .Call<IPersonFacade>()
                    .WithQuery(f => f.GetActivePersonsFor("CZ"), list =>
                        {
                            list.First();
                            Assert.IsNotNull(list);
                        })
                    .WithQuery(f => f.GetActivePersonsFor("DE"), (list) =>
                        {
                            list.First();
                            Assert.IsNotNull(list);
                        })
                .Call<ICountryFacade>()
                .WithQuery(f => f.GetByCode("CZ"), country => Assert.IsNotNull(country))
                .Execute();

            factory
                .Call<ICompanyService>()
                .WithQuery(c => c.GetActiveCompanies(), companies => Assert.IsNotNull(companies))
                .Execute();
        }

        [TestMethod]
        public void BatchFactoryTEST_NestedObjects()
        {
            IBatchBuilder factory = new AsyncBatchBuilder();

            factory
                .Call<ICompanyService>()
                .WithQuery(c => c.GetActiveCompanies(), companies => Assert.IsNotNull(companies))
                .Execute();
        }

        [TestMethod]
        public void BatchFactoryTEST_PrimitiveObjectAsResult()
        {
            IBatchBuilder factory = new AsyncBatchBuilder();
            
            factory
                .Call<ICountryFacade>()
                .WithQuery(c => c.IsCountryValid("sdsd"), result => Assert.IsTrue(result.HasValue && result.Value))
                .WithQuery(c => c.IsValidNonNulable("sdf"), (result) => Assert.IsNotNull(result))
            .Execute();
        }

        [TestMethod]
        public void BatchFactoryTEST_VoidAsResult()
        {
            IBatchBuilder factory = new AsyncBatchBuilder();

            factory
                .Call<ICountryFacade>()
                .WithCommand(c => c.VoidMethod("sdsd"), () => Assert.IsTrue(true))
                //.WithQuery(c => c.IsValidNonNulable("sdf"), (result) => Assert.IsNotNull(result))
            .Execute();
        }

        [TestMethod]
        public void BatchFactoryTEST_CompletedAction()
        {
            IBatchBuilder factory = new AsyncBatchBuilder();

            factory
                .Call<ICountryFacade>()
                .WithQuery(c => c.IsCountryValid("asd"), (result) => Assert.IsNotNull(result))
                .WhenCompleted((result) => Assert.IsNotNull(result))
                .WhenCompleted((result) => Assert.IsNotNull(result))
                .Execute();
        }

        //[TestMethod]
        //public void BatchFactoryTEST_MethodOnSeverWillThrowException()
        //{
        //    IBatchBuilder factory = new AsyncBatchBuilder();

        //    factory
        //        .Call<ICountryFacade>()
        //        .WithQuery(c => c.ThrowExceptionMethod("sdf"), (result) => Assert.IsNotNull(result))
        //        .WithQuery(c => c.IsCountryValid("asd"), (result) => Assert.IsNotNull(result))
        //        .WhenCompleted((result) => Assert.IsNotNull(result))
        //        .WhenCompleted((result) => Assert.IsNotNull(result))
        //        .Execute();
        //}


        [TestMethod]
        public void BatchFactoryAsync_Using_RrslConfiguration()
        {
            IBatchBuilder factory = RrslLiteConfiguration.Instance.BatchBuilderConfiguration.GetAsyncBatchBuilder();

            factory
                .Call<IPersonFacade>()
                .WithQuery(f => f.GetActivePersonsFor("CZ"), list =>
                {
                    Assert.IsNotNull(list);
                })
                .WithQuery(f => f.GetMostImportantPersonFor("DE"), person =>
                {
                    Assert.IsNotNull(person);
                })
                .Call<ICountryFacade>()
                .WithQuery(f => f.GetByCode("CZ"), country =>
                {
                    Assert.IsNotNull(country);
                })
                .Execute();


        }

        [TestMethod]
        public void BatchFactoryAsync_Using_INotifyPropertyChangedInterceptor()
        {

            IBatchBuilder factory = RrslLiteConfiguration.Instance.BatchBuilderConfiguration.GetAsyncBatchBuilder();

            factory
                .Call<ICompanyService>()
                .WithQuery(f => f.GetActiveCompanies(), list =>
                {
                    Assert.IsNotNull(list);
                    Assert.IsInstanceOfType(list, typeof(INotifyPropertyChanged));
                    Assert.IsInstanceOfType(list.First(), typeof(INotifyPropertyChanged));
                    Assert.IsInstanceOfType(list.First().Addresses, typeof(INotifyPropertyChanged));
                    Assert.IsInstanceOfType(list.First().Addresses.First(), typeof(INotifyPropertyChanged));

                })
                .Execute();


        }

        [TestMethod]
        public void BatchFactoryAsync_Using_INotifyPropertyChangedInterceptor_Send_To_Server()
        {
            IList<Company> data = null;

            RrslLiteConfiguration.Instance.BatchBuilderConfiguration.GetAsyncBatchBuilder()
                .Call<ICompanyService>()
                .WithQuery(f => f.GetActiveCompanies(), list =>
                                                       {
                                                           data = list;

                                                           RrslLiteConfiguration.Instance.BatchBuilderConfiguration.
                                                               GetAsyncBatchBuilder()
                                                               .Call<ICompanyService>()
                                                               .WithCommand(f => f.SetActiveCompany((Company) data.First()),
                                                                     () =>
                                                                         {
                                                                             Assert.IsTrue(true);
                                                                         })
                                                               .Execute();
                                                       })
                .Execute();
        }

        [TestMethod]
        public void BatchFactoryAsync_Calling_ServerService_Concurently()
        {
            RrslLiteConfiguration.Instance.BatchBuilderConfiguration
                .BatchCallBuilderConfiguration
                .WithMessageCreator(
                    (correlationId) => new Message(correlationId) {  }
                    );

            IBatchBuilder factory = RrslLiteConfiguration.Instance.BatchBuilderConfiguration.GetAsyncBatchBuilder();

            factory
                .Call<IPersonFacade>()
                .WithCommand(f => f.LongRunning(), () =>
                {
                    
                })
                .Execute();

            factory = RrslLiteConfiguration.Instance.BatchBuilderConfiguration.GetAsyncBatchBuilder();

            factory
                .Call<IPersonFacade>()
                .WithCommand(f => f.ShortRunning(), () =>
                {
                    
                })
                .Execute();
        }
    }
}
